package tls

import (
	"github.com/pkg/errors"
	"golang.org/x/crypto/ssh"

	"github.com/openshift/installer/pkg/asset"
)

// BootstrapSSHKeyPair generates a private, public key pair for SSH.
// These keys can use to used to configure the bootstrap-host so that the private key can be
// used to connect.
type BootstrapSSHKeyPair struct {
	Priv []byte // private key
	Pub  []byte // public ssh key
}

const bootstrapSSHKeyPairFilenameBase = "bootstrap-ssh"

var _ asset.Asset = (*BootstrapSSHKeyPair)(nil)

// Dependencies lists the assets required to generate the BootstrapSSHKeyPair.
func (a *BootstrapSSHKeyPair) Dependencies() []asset.Asset {
	return []asset.Asset{}
}

// Name defines a user freindly name for BootstrapSSHKeyPair.
func (a *BootstrapSSHKeyPair) Name() string {
	return "Bootstrap SSH Key Pair"
}

// Generate generates the key pair based on its dependencies.
func (a *BootstrapSSHKeyPair) Generate(dependencies asset.Parents) error {
	kp := KeyPair{}
	if err := kp.Generate(bootstrapSSHKeyPairFilenameBase); err != nil {
		return errors.Wrap(err, "failed to generate key pair")
	}

	publicRSAKey, err := PemToPublicKey(kp.Pub)
	if err != nil {
		return errors.Wrap(err, "failed to parse the public RSA key")
	}

	publicSSHKey, err := ssh.NewPublicKey(publicRSAKey)
	if err != nil {
		return errors.Wrap(err, "failed to create public SSH key from public RSA key")
	}

	a.Priv = kp.Private()
	a.Pub = ssh.MarshalAuthorizedKey(publicSSHKey)

	return nil
}

// Public returns the public SSH key.
func (a *BootstrapSSHKeyPair) Public() []byte {
	return a.Pub
}

// Private returns the private key.
func (a *BootstrapSSHKeyPair) Private() []byte {
	return a.Priv
}

// Files returns the files generated by the asset.
func (a *BootstrapSSHKeyPair) Files() []*asset.File {
	return []*asset.File{{
		Filename: assetFilePath(bootstrapSSHKeyPairFilenameBase + ".key"),
		Data:     a.Priv,
	}, {
		Filename: assetFilePath(bootstrapSSHKeyPairFilenameBase + ".pub"),
		Data:     a.Pub,
	}}
}

// Load is a no-op because the service account keypair is not written to disk.
func (a *BootstrapSSHKeyPair) Load(asset.FileFetcher) (bool, error) {
	return false, nil
}
